package ming.util.base;

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Jackson工具类，提供Map或Entity与Json的互相转换, 性能比Gson高5~10倍
 * 
 */
public class JsonUtil {
	protected static Logger logger = LoggerFactory.getLogger(JsonUtil.class);
	// members
	private static final ObjectMapper mapper = new ObjectMapper();

	// static block
	static {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		SerializationConfig serializationConfig = mapper.getSerializationConfig();
		serializationConfig.withDateFormat(simpleDateFormat);
		mapper.setSerializationConfig(serializationConfig);
		DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
		deserializationConfig.withDateFormat(simpleDateFormat);
		mapper.setDateFormat(simpleDateFormat);
		// 使用单引号
		mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
		mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
		mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		// 禁止使用int代表Enum的order()來反序列化Enum,非常危險
		mapper.configure(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
	}


	/**
	 * 将Map接口类型序列化为Json字符串
	 * 
	 * @param map
	 *            Map接口类型
	 * @return 返回Json字符串
	 */
	public static String toJson(Map map) {
		String actual = "";
		try {
			// 采用StringWriter方式可以大大提高转换的性能
			StringWriter stringWriter = new StringWriter();
			JsonGenerator jsonGenerator = new JsonFactory().createJsonGenerator(stringWriter);
			mapper.writeValue(jsonGenerator, map);
			actual = stringWriter.toString();
			jsonGenerator.close();
			stringWriter.close();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return actual;
	}

	/**
	 * 将Json字符串反序列化为Map接口类型
	 * 
	 * @param jsonString
	 *            Json字符串
	 * @return 返回Map接口类型
	 */
	public static Map toMap(String jsonString) {
		Map map = null;
		try {
			map = mapper.readValue(jsonString, LinkedHashMap.class);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return map;
	}

	/**
	 * 将实体序列化为Json字符串
	 * 
	 * @param entity
	 *            传入要转换的实体，支持List
	 * @return 返回Json字符串
	 */
	public static String fromEntity(Object entity) {
		String actual = "";
		try {
			StringWriter stringWriter = new StringWriter();
			JsonGenerator jsonGenerator = new JsonFactory().createJsonGenerator(stringWriter);
			mapper.writeValue(jsonGenerator, entity);
			actual = stringWriter.toString();
			jsonGenerator.close();
			stringWriter.close();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		try {
			actual = new String(actual.getBytes(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return actual;
	}

	/**
	 * 将实体序列化为Json字符串
	 * 
	 * @param entity
	 *            传入要转换的实体，支持List
	 * @return 返回Json字符串
	 */
	public static String listToArrayJson(List list) {
		if (null == list) {
			return "[]";
		}
		StringBuffer sb = new StringBuffer("[");
		int i = 0;
		for (Object obj : list) {
			String temp = JsonUtil.fromEntity(obj);
			sb.append(temp);
			if (i + 1 < list.size()) {
				sb.append(",");
			}
			i++;
		}
		sb.append("]");
		return sb.toString();
	}

	/**
	 * 将JSON反序列化为实体或实体集合
	 * 
	 * @param jsonString
	 *            Json字符串
	 * @param typeRef
	 *            目标类型
	 * @param <T>
	 *            目标类型
	 * @return 类型为T的实体或实体集合
	 */
	public static <T> T toEntity(String jsonString, TypeReference typeRef) {
		Object actual = null;
		try {
			actual = mapper.readValue(jsonString, typeRef);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (actual == null) {
			return null;
		}
		return (T) actual;
	}

	/**
	 * 将JSON转换为Jackson的ObjectNode
	 * 
	 * @param jsonString
	 *            Json字符串
	 * @return ObjectNode
	 */
	public static ObjectNode toJsonNode(String jsonString) {
		ObjectNode actual = null;
		try {
			actual = mapper.readValue(jsonString, ObjectNode.class);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return actual;
	}

	/**
	 * 将Map转换为Jackson的ObjectNode
	 * 
	 * @param map
	 *            被转换的对象
	 * @return ObjectNode
	 */
	public static ObjectNode toJsonNode(Map map) {
		ObjectNode actual = JsonUtil.toJsonNode(JsonUtil.toJson(map));
		return actual;
	}
}
